1   /*
2    * Copyright (C) 2007 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect.testing.testers;
18  
19  import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
20  import static com.google.common.collect.testing.features.CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION;
21  import static com.google.common.collect.testing.features.CollectionFeature.RESTRICTS_ELEMENTS;
22  import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ADD;
23  import static com.google.common.collect.testing.features.CollectionSize.ZERO;
24  import static java.util.Collections.singletonList;
25  
26  import com.google.common.annotations.GwtCompatible;
27  import com.google.common.annotations.GwtIncompatible;
28  import com.google.common.collect.testing.AbstractCollectionTester;
29  import com.google.common.collect.testing.Helpers;
30  import com.google.common.collect.testing.MinimalCollection;
31  import com.google.common.collect.testing.features.CollectionFeature;
32  import com.google.common.collect.testing.features.CollectionSize;
33  
34  import java.lang.reflect.Method;
35  import java.util.ConcurrentModificationException;
36  import java.util.Iterator;
37  import java.util.List;
38  
39  /**
40   * A generic JUnit test which tests addAll operations on a collection. Can't be
41   * invoked directly; please see
42   * {@link com.google.common.collect.testing.CollectionTestSuiteBuilder}.
43   *
44   * @author Chris Povirk
45   * @author Kevin Bourrillion
46   */
47  @SuppressWarnings("unchecked") // too many "unchecked generic array creations"
48  @GwtCompatible(emulated = true)
49  public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
50    @CollectionFeature.Require(SUPPORTS_ADD)
51    public void testAddAll_supportedNothing() {
52      assertFalse("addAll(nothing) should return false",
53          collection.addAll(emptyCollection()));
54      expectUnchanged();
55    }
56  
57    @CollectionFeature.Require(absent = SUPPORTS_ADD)
58    public void testAddAll_unsupportedNothing() {
59      try {
60        assertFalse("addAll(nothing) should return false or throw",
61            collection.addAll(emptyCollection()));
62      } catch (UnsupportedOperationException tolerated) {
63      }
64      expectUnchanged();
65    }
66  
67    @CollectionFeature.Require(SUPPORTS_ADD)
68    public void testAddAll_supportedNonePresent() {
69      assertTrue("addAll(nonePresent) should return true",
70          collection.addAll(createDisjointCollection()));
71      expectAdded(samples.e3, samples.e4);
72    }
73  
74    @CollectionFeature.Require(absent = SUPPORTS_ADD)
75    public void testAddAll_unsupportedNonePresent() {
76      try {
77        collection.addAll(createDisjointCollection());
78        fail("addAll(nonePresent) should throw");
79      } catch (UnsupportedOperationException expected) {
80      }
81      expectUnchanged();
82      expectMissing(samples.e3, samples.e4);
83    }
84  
85    @CollectionFeature.Require(SUPPORTS_ADD)
86    @CollectionSize.Require(absent = ZERO)
87    public void testAddAll_supportedSomePresent() {
88      assertTrue("addAll(somePresent) should return true",
89          collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
90      assertTrue("should contain " + samples.e3, collection.contains(samples.e3));
91      assertTrue("should contain " + samples.e0, collection.contains(samples.e0));
92    }
93  
94    @CollectionFeature.Require(absent = SUPPORTS_ADD)
95    @CollectionSize.Require(absent = ZERO)
96    public void testAddAll_unsupportedSomePresent() {
97      try {
98        collection.addAll(MinimalCollection.of(samples.e3, samples.e0));
99        fail("addAll(somePresent) should throw");
100     } catch (UnsupportedOperationException expected) {
101     }
102     expectUnchanged();
103   }
104 
105   @CollectionFeature.Require({SUPPORTS_ADD,
106       FAILS_FAST_ON_CONCURRENT_MODIFICATION})
107   @CollectionSize.Require(absent = ZERO)
108   public void testAddAllConcurrentWithIteration() {
109     try {
110       Iterator<E> iterator = collection.iterator();
111       assertTrue(collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
112       iterator.next();
113       fail("Expected ConcurrentModificationException");
114     } catch (ConcurrentModificationException expected) {
115       // success
116     }
117   }
118 
119   @CollectionFeature.Require(absent = SUPPORTS_ADD)
120   @CollectionSize.Require(absent = ZERO)
121   public void testAddAll_unsupportedAllPresent() {
122     try {
123       assertFalse("addAll(allPresent) should return false or throw",
124           collection.addAll(MinimalCollection.of(samples.e0)));
125     } catch (UnsupportedOperationException tolerated) {
126     }
127     expectUnchanged();
128   }
129 
130   @CollectionFeature.Require(value = {SUPPORTS_ADD,
131       ALLOWS_NULL_VALUES}, absent = RESTRICTS_ELEMENTS)
132   public void testAddAll_nullSupported() {
133     List<E> containsNull = singletonList(null);
134     assertTrue("addAll(containsNull) should return true", collection
135         .addAll(containsNull));
136     /*
137      * We need (E) to force interpretation of null as the single element of a
138      * varargs array, not the array itself
139      */
140     expectAdded((E) null);
141   }
142 
143   @CollectionFeature.Require(value = SUPPORTS_ADD,
144       absent = ALLOWS_NULL_VALUES)
145   public void testAddAll_nullUnsupported() {
146     List<E> containsNull = singletonList(null);
147     try {
148       collection.addAll(containsNull);
149       fail("addAll(containsNull) should throw");
150     } catch (NullPointerException expected) {
151     }
152     expectUnchanged();
153     expectNullMissingWhenNullUnsupported(
154         "Should not contain null after unsupported addAll(containsNull)");
155   }
156 
157   @CollectionFeature.Require(SUPPORTS_ADD)
158   public void testAddAll_nullCollectionReference() {
159     try {
160       collection.addAll(null);
161       fail("addAll(null) should throw NullPointerException");
162     } catch (NullPointerException expected) {
163     }
164   }
165 
166   /**
167    * Returns the {@link Method} instance for {@link
168    * #testAddAll_nullUnsupported()} so that tests can suppress it with {@code
169    * FeatureSpecificTestSuiteBuilder.suppressing()} until <a
170    * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5045147">Sun
171    * bug 5045147</a> is fixed.
172    */
173   @GwtIncompatible("reflection")
174   public static Method getAddAllNullUnsupportedMethod() {
175     return Helpers.getMethod(CollectionAddAllTester.class, "testAddAll_nullUnsupported");
176   }
177 
178   /**
179    * Returns the {@link Method} instance for {@link
180    * #testAddAll_unsupportedNonePresent()} so that tests can suppress it with
181    * {@code FeatureSpecificTestSuiteBuilder.suppressing()} while we figure out
182    * what to do with <a href="http://goo.gl/qJBruX">{@code ConcurrentHashMap}
183    * support for {@code entrySet().add()}</a>.
184    */
185   @GwtIncompatible("reflection")
186   public static Method getAddAllUnsupportedNonePresentMethod() {
187     return Helpers.getMethod(CollectionAddAllTester.class, "testAddAll_unsupportedNonePresent");
188   }
189 
190   /**
191    * Returns the {@link Method} instance for {@link
192    * #testAddAll_unsupportedSomePresent()} so that tests can suppress it with
193    * {@code FeatureSpecificTestSuiteBuilder.suppressing()} while we figure out
194    * what to do with <a href="http://goo.gl/qJBruX">{@code ConcurrentHashMap}
195    * support for {@code entrySet().add()}</a>.
196    */
197   @GwtIncompatible("reflection")
198   public static Method getAddAllUnsupportedSomePresentMethod() {
199     return Helpers.getMethod(CollectionAddAllTester.class, "testAddAll_unsupportedSomePresent");
200   }
201 }